package com.bbz.core.nio.chapter1;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetAddress;
import java.net.InetSocketAddress;

/**
 * 绑定服务器将在其上监听并接受链接请求的端口
 * 配置Channel，将有关的入站信息通知给EchoServiceHandler
 */
public class EchoService {
    private final int port;
    public EchoService(int port){
        this.port=port;
    }
    public static  void main(String args[]){
        if(args.length!=1){
            System.err.print("Usage:"+EchoService.class.getSimpleName()+"<port>");
        }
        int port=Integer.parseInt(args[0]);
        try {
            new EchoService(port).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start()throws  Exception{
        final EchoServerHandler serverHandler=new EchoServerHandler();
        //创建并分配一个NioEventLoopGroup 实例以进行事件的处理，如接受新连接以及读/数据
        EventLoopGroup group=new NioEventLoopGroup();
        try{
            //创建一个ServerBootstrap 的实例以引导和绑定服务器；
            ServerBootstrap serverBootstrap=new ServerBootstrap();
            serverBootstrap.group(group)
                    .channel(NioServerSocketChannel.class)
                    //指定服务器绑定的本地的InetSocketAddress；
                    .localAddress(new InetSocketAddress(port))
                    //使用一个EchoServerHandler 的实例初始化每一个新的Channel；
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception{
                            ch.pipeline().addLast(serverHandler);
                        }
                    });
            //调用ServerBootstrap.bind()方法以绑定服务器。
            ChannelFuture f=serverBootstrap.bind().sync();
            //获取Channel 的CloseFuture，并且阻塞当前线程直到它完成
            f.channel().closeFuture().sync();
        }finally {
            //关闭EventLoopGroup，释放所有的资源
            group.shutdownGracefully().sync();
        }
    }
}
